import {inject, InjectionKey, provide, reactive, readonly as defineReadOnly, UnwrapRef} from "vue";

export interface BuildContextOptions {
  readonly?: boolean; // 只读对象 只可取，不可存
  createProvider?: boolean; // 是否创建一个provide对象
  native?: boolean;// 若为false 是 响应式的
}

type ShallowUnwrap<T> = {
  [P in keyof T]: UnwrapRef<T[P]>;
};

/**
 * 在 Vue 3 中通过 provide 提供数据
 *
 * @param context {any} provide 存放的上下文对象
 * @param key {InjectionKey} provide 存放的上下文对象的key
 * @param options {BuildContextOptions} 类型
 */

export function createContext<T>(context: any, key: InjectionKey<T> = Symbol(), options: BuildContextOptions = {}) {
  const { readonly = true, createProvider = false, native = false } = options;

  const state = reactive(context);
  // 只读对象
  const provideData = readonly ? defineReadOnly(state) : state;
  // provide 提供数据
  !createProvider && provide(key, native ? context : provideData);
  return {
    state,
  };
}

export function useContext<T>(key: InjectionKey<T>, native?: boolean): T;
export function useContext<T>(key: InjectionKey<T>, defaultValue?: any, native?: boolean): T;

/**
 * 在 Vue 3 中获取通过 provide 提供的上下文
 *
 * @param key {InjectionKey} provide 上下文对象的key
 * @param defaultValue defaultValue 默认值
 *
 */
export function useContext<T>(key: InjectionKey<T> = Symbol(), defaultValue?: any): ShallowUnwrap<T> {
  return inject(key, defaultValue || {});
}